package com.briup.es.service.impl;

import com.briup.es.config.auth.SecurityUserContext;
import com.briup.es.config.exception.ServiceException;
import com.briup.es.config.response.ResultCode;
import com.briup.es.domain.bean.User;
import com.briup.es.domain.dto.UserLoginDTO;
import com.briup.es.domain.dto.UserDTO;
import com.briup.es.domain.dto.UserUpdatePasswordDTO;
import com.briup.es.mapper.UserMapper;
import com.briup.es.service.UserService;
import com.briup.es.utils.BeanUtil;
import com.briup.es.utils.JwtUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Map;
import java.util.Objects;

@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {

    private final UserMapper userMapper;

    @Override
    public void register(UserDTO registerDTO) {
        // 判断用户注册的用户名是否已经存在
        User userFromDB = userMapper.queryByUsername(registerDTO.getUsername());

        if (userFromDB != null){
            throw new ServiceException(ResultCode.USER_IS_EXISTS);
        }

        // 将用户注册dto实体转换为 User 实体对象
        User user = BeanUtil.bean2VO(registerDTO, User.class);
        // 将当前时间设置为注册时间
        user.setRegisterTime(LocalDateTime.now());

        userMapper.addUser(user);
    }

    @Override
    public Map<String, Object> login(UserLoginDTO loginDTO) {
        String username = loginDTO.getUsername();
        String password = loginDTO.getPassword();

        // 根据用户名查询该用户是否存在
        User user = userMapper.queryByUsername(username);
        if (user == null){
            throw new ServiceException(ResultCode.USER_IS_NOT_EXISTS);
        }
        // 用户存在，继续比较用户的密码
        if (!password.equals(user.getPassword())){
            throw new ServiceException(ResultCode.PASSWORD_IS_ERROR);
        }
        // 密码也相同，进一步校验账号是否被封禁
        if (user.getStatus() == 1){
            throw new ServiceException(ResultCode.ACCOUNT_IS_UNABLE);
        }

        // 根据用户信息生成 token （token需要具备 防篡改、携带部分数据、过期失效 等功能）
        Map<String, Object> claims = Map.of("userId", user.getId(),
                "username", user.getUsername());
        // 签发token
        String token = JwtUtil.sign(claims);

        return Map.of("jwt",token,"userInfo",user);
    }

    @Override
    public User queryById(Integer userId) {
        return userMapper.queryById(userId);
    }

    @Override
    public void updatePassword(UserUpdatePasswordDTO passwordDTO) {
        // 当前登录用户从认证上下文中获取
        User user = SecurityUserContext.currentUser();

        // 比较用户输入的原始密码与数据库中查询的密码是否一致
        if (!user.getPassword().equals(passwordDTO.getOldPassword())){
            throw new ServiceException(ResultCode.OLD_PASSWORD_IS_ERROR);
        }

        // 用户输入的原始密码认证无误，那么就可以继续修改密码
        UserDTO userDTO = BeanUtil.bean2VO(user, UserDTO.class);
        userDTO.setPassword(passwordDTO.getNewPassword());

        // 修改用户数据
        userMapper.updateUser(userDTO);
    }

    @Override
    public void updateUser(UserDTO userDTO) {
        // 先对数据进行校验，如保证用户名必须唯一
        String username = userDTO.getUsername();
        User user = userMapper.queryByUsername(username);
        // 如果根据用户名查询用户，该用户对象不为null，并且该用户的id与你的id不一致，那么说明该用户名已经被占用
        if (user!=null && !Objects.equals(user.getId(), SecurityUserContext.userId())){
            throw new ServiceException(ResultCode.USER_IS_EXISTS);
        }

        // 修改用户数据
        userMapper.updateUser(userDTO);
    }
}
